home *** CD-ROM | disk | FTP | other *** search
/ Magnum One / Magnum One (Mid-American Digital) (Disc Manufacturing).iso / d12 / ecstr2.arc / STRKEY.C < prev    next >
C/C++ Source or Header  |  1987-03-04  |  5KB  |  147 lines

  1. /*  File   : strkey.c
  2.     Author : Richard A. O'Keefe.
  3.     Updated: 20 April 1984
  4.     Defines: strkey()
  5.  
  6.     strkey(dst, head, tail, options)
  7.        copies tail-head characters from head to dst according to the
  8.        options.  If tail is NullS, it copies up to the terminating
  9.        NUL of head.  This function is meant for doing comparisons as
  10.        by sort(1).  The options are thus a string of characters
  11.        taken from "bdfin".  In case the options came from somewhere
  12.        else other letters are ignored.
  13.  
  14.        -b: leading layout characters are not copied.
  15.  
  16.        -d: only letters, digits, and blanks are copied.
  17.        -i: only graphic characters (32..126) are copied.
  18.        -n: a numeric string is copied.
  19.            These options are incompatible, and the last is taken.
  20.  
  21.        -f: upper case letters are copied as lower case.
  22.  
  23.     The question of what to do with a numeric string is  an  interesting
  24.     one,  and  I  don't claim that this is a brilliant answer.  However,
  25.     the solution used here does mean that the  caller  can  compare  two
  26.     strings as strings without needing to know that they are numeric.  A
  27.     number  is  copied  as  <sign><9  digits>.<remaining  digits>, where
  28.     <sign> is '-' for a negative number and '0' for a  positive  number.
  29.     The magic number 9 is defined to be DigitMagic.
  30.  
  31.     The idea is that to compare two lines using the keys
  32.        -tx +m1.n1<flags> -m2.n2
  33.     you do
  34.        h1 = strfield(line1, m1, n1, 0, 'x');
  35.        t1 = strfield(h1, 1, 0, 0, 'x');
  36.        strkey(buff1, h1, t1, "flags");
  37.        h2 = strfield(line2, m2, n2, 0, 'x');
  38.        t2 = strfield(h2, 1, 0, 0, 'x');
  39.        strkey(buff2, h2, t2, "flags");
  40.        ... strcmp(buff1, buff2) ...
  41.  
  42.     The point of all this, of course, is to make it easier to write new
  43.     utilities which are compatible with sort(1) than ones which are not.
  44. */
  45.  
  46. #include "strings.h"
  47.  
  48. #define        DigitMagic 9
  49.  
  50. char *strkey(dst, head, tail, flags)
  51.     register char *dst, *head, *tail;
  52.     char *flags;
  53.     {
  54.        register int c;
  55.        int b = 0;      /* b option? */
  56.        int f = 0;      /* f option? */
  57.        int k = 0;      /* 3->n, 2->d, 1->i, 0->none of them */
  58.  
  59.        while (*flags) switch (*flags++|32) {
  60.            case 'b':   b++;    break;
  61.            case 'f':   f++;    break;
  62.            case 'i':   k = 1;  break;
  63.            case 'd':   k = 2;  break;
  64.            case 'n':   k = 3;  break;
  65.            default : /*ignore*/break;
  66.        }
  67.        flags = dst;    /* save return value */
  68.  
  69.        if (tail == NullS) for (tail = head; *tail; tail++) ;
  70.  
  71.        if (b) while (head != tail && *head <= ' ') head++;
  72.  
  73.        switch (k) {
  74.            case 0:
  75.              if (f) {
  76.                    while (head != tail) {
  77.                        c = *head++;
  78.                        if (c >= 'A' && c <= 'Z') c |= 32;
  79.                        *dst++ = c;
  80.                    }
  81.                } else {
  82.                    while (head != tail) *dst++ = *head++;
  83.                }
  84.                break;
  85.            case 1:
  86.                if (f) {
  87.                    while (head != tail) {
  88.                        c = *head++;
  89.                        if (c >= 32 && c <= 126) {
  90.                            if (c >= 'A' && c <= 'Z') c |= 32;
  91.                            *dst++ = c;
  92.                        }
  93.                    }
  94.                } else {
  95.                    while (head != tail) {
  96.                        c = *head++;
  97.                        if (c >= 32 && c <= 126) *dst++ = c;
  98.                  }
  99.                }
  100.                break;
  101.            case 2:
  102.                if (f) f = 32;
  103.                while (head != tail) {
  104.                    c = *head++;
  105.            if (c >= '0' && c <= '9' ||  c >= 'a' && c <= 'z' || c == '') {
  106.                        *dst++ = c;
  107.                    } else
  108.                    if (c >= 'A' && c <= 'Z') {
  109.                        *dst++ = c|f;
  110.                    }
  111.                }
  112.                break;
  113.            case 3:
  114.                if (*head == '-' && head != tail) {
  115.                    *dst++ = *head++;
  116.                    head++;
  117.                } else {
  118.                    *dst++ = '0';
  119.                }
  120.              b = 0;
  121.                while (head != tail) {
  122.                    c = *head;
  123.                    if (c < '0' || c > '9') break;
  124.                    b++, head++;
  125.                }
  126.                f = DigitMagic-b;
  127.                while (--f >= 0) *dst++ = '0';
  128.                head -= b;
  129.                while (--b >= 0) *dst++ = *head++;
  130.                if (*head == '.' && head != tail) {
  131.                    *dst++ = *head++;
  132.                    while (head != tail) {
  133.                        c = *head++;
  134.                        if (c < '0' || c > '9') break;
  135.                        *dst++ = c;
  136.                    }
  137.                /* now remove trailing 0s and possibly the '.' as well */
  138.                    while (*--dst == '0') ;
  139.                    if (*dst != '.') dst++;
  140.                }
  141.                break;
  142.        }
  143.      *dst = NUL;
  144.        return flags;   /* saved initial value of dst */
  145.     }
  146.  
  147.